﻿
using LibNiconico.NiconicoApi.Extentions;
using LibNiconico.NiconicoApi.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LibNiconico.NiconicoApi.Internal
{
    /// <summary>
    /// Xmlでやりとりするコメントクライアント
    /// </summary>
    internal abstract class NicoXmlCommentClient
    {

        
        /// <summary>
        /// Xmlコメントクライアント用接続情報
        /// </summary>
        protected NicoCommentConnectionInfoBase XmlConnectionInfo { get; set; }

        /// <summary>
        /// 認証情報
        /// </summary>
        protected NiconicoAuth Auth;

        /// <summary>
        /// このコメントクライアントに割り当てられている生成情報
        /// </summary>
        internal NiconicoApiInfoGetCreateInfo DefaultCreateInfo;


        internal SynchronizationContext SynchronizationContext;




        internal NicoXmlCommentClient(NiconicoAuth auth, NiconicoApiInfoGetCreateInfo createInfo, SynchronizationContext synchronizationContext)
        {
            Auth = auth;
            DefaultCreateInfo = createInfo;
            this.SynchronizationContext = synchronizationContext;
        }

        /// <summary>
        /// Xmlのコメント読み取り
        /// </summary>
        /// <param name="message"></param>
        /// <param name="readChat"></param>
        /// <returns></returns>
        internal protected void ReadXmlMessage(XElement message,Action<XElement> readChat){



            switch (message.Name.LocalName)
            {
                case "thread":
                    OnPrivateReadThread(message);
                    break;

                case "chat":

                    readChat(message);
                    break;

                case "chat_result":
                    OnProtectedReadChatResult(message);
                    break;
            }


            

        }

        /// <summary>
        /// 受信要求コメント生成
        /// </summary>
        /// <param name="connectionInfo"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        protected static XElement CreateReceiveRequestMessage(NicoCommentConnectionInfoBase connectionInfo, NicoReceiveRequestBase req)
        {
            XElement element = new XElement("thread");
            element.SetAttributeValue("thread", connectionInfo.Thread);
            element.SetAttributeValue("res_from", req.ResFrom.ToString());
            element.SetAttributeValue("version", req.Version);
            return element;

        }

        

        private void OnPrivateReadThread(XElement message)
        {

            OnProtectedReadThread(message);
        }

        /// <summary>
        /// 送信用コメント生成
        /// </summary>
        /// <param name="comment"></param>
        /// <returns></returns>
        protected  XElement CreateSubmitChatComment( NicoSubmitChatCommentBase comment)
        {
            XElement message = new XElement("chat");
            message.SetAttributeValue("thread", this.XmlConnectionInfo.Thread);



            if (comment.Mails.Count > 0) message.SetAttributeValue("mail", string.Join(" ", comment.Mails));

            if (comment.Body != NicoSubmitChatCommentBase.INITIAL_BODY) message.Value = comment.Body;
           
            return message;
            
        }

        /// <summary>
        /// 接続停止イベントを発生させる
        /// </summary>
        /// <param name="reason"></param>
        /// <param name="e"></param>
        protected abstract void OnProtectedClose(string reason, Exception e);



        /// <summary>
        /// コメント読み取り中に例外が発生したイベントを発生させる
        /// </summary>
        /// <param name="e"></param>
        protected abstract void OnProtectedReadException(Exception e);

        /// <summary>
        /// 送信結果読み取りイベントを発生させる
        /// </summary>
        /// <param name="message"></param>
        protected abstract void OnProtectedReadChatResult(XElement message);



        /// <summary>
        /// スレッドコメントを発生させる
        /// </summary>
        /// <param name="message"></param>
        protected abstract void OnProtectedReadThread(XElement message);


        
    }
}
